
package com.scs.application.modules.base.service.impl;

import cn.afterturn.easypoi.excel.entity.ImportParams;
import cn.afterturn.easypoi.excel.entity.result.ExcelImportResult;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.google.common.collect.Lists;
import com.scs.application.core.exceptions.BusinessException;
import com.scs.application.core.model.ImportResult;
import com.scs.application.core.model.RestResult;
import com.scs.application.core.service.BaseServiceImpl;
import com.scs.application.core.thread.BatchSaveTask;
import com.scs.application.core.thread.DefaultSaveHandler;
import com.scs.application.core.utils.*;
import com.scs.application.modules.base.dto.*;
import com.scs.application.modules.base.entity.*;
import com.scs.application.modules.base.enums.ExcelImportBaseDataConfig;
import com.scs.application.modules.base.mapper.HospitalMaterialMapper;
import com.scs.application.modules.base.mapper.MaterialMapper;
import com.scs.application.modules.base.mapper.MaterialSpecMapper;
import com.scs.application.modules.base.request.MaterialQueryRequest;
import com.scs.application.modules.base.service.*;
import com.scs.application.modules.base.vo.ExcelMaterialVO;
import com.scs.application.modules.base.vo.MaterialVO;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.Serializable;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;


/**
 * 商品 service 实现
 */
@AllArgsConstructor
@Slf4j
@Service
public class MaterialServiceImpl extends BaseServiceImpl<MaterialMapper, Material> implements MaterialService {


    private final MaterialSpecService materialSpecService;
    private final MaterialSpecMapper materialSpecMapper;

    private final SupplierService supplierService;

    private final ManufacturerService manufacturerService;

    private final MaterialCatalogService materialCatalogService;

    private final HospitalMaterialMapper hospitalMaterialMapper;


    @Override
    public IPage<MaterialVO> page(MaterialQueryRequest request) {
        request.setSupplierId(UserUtils.isSupplier() ? UserUtils.getSupplierId() : null);
        return this.baseMapper.page(request.getPage(), request);
    }

    @Override
    public List<MaterialVO> list(MaterialQueryRequest request) {
        request.setSupplierId(UserUtils.isSupplier() ? UserUtils.getSupplierId() : null);
        List<MaterialVO> list = this.baseMapper.list(request);
        return list;
    }

    @Override
    public List<ExcelMaterialVO> listExcel(MaterialQueryRequest request) {
        return this.baseMapper.listExcel(request);
    }

    @Override
    public void autoCorrectionCatalog(AutoCorrectionCatalogDTO dto) {
        /**
         * forceAll 强制修改所有，当为 {@code false} 时，只会更新catalog_id = 0 的数据
         * todayCreate 所选择日期的数据，当为 {@code true} 时，只会更新gmt_create > 今日的数据
         */
        boolean forceAll = dto.isForceAll();
        Date beginCreatedDate = dto.getBeginCreatedDate();
        Date endCreatedDate = dto.getEndCreatedDate();

        QueryWrapper<Material> wrapper = Wrappers.<Material>query().select("id,certificate_no,approval_no")
                .isNotNull("certificate_no");

        if (UserUtils.isSupplier()) {
            // 管理员，修正所有数据
            wrapper.eq("supplier_id", UserUtils.getSupplierId());
        }
        if (!forceAll) {
            wrapper.eq("catalog_id", 0);
        }
        if (beginCreatedDate == null || endCreatedDate == null) {
            Date now = new Date();
            wrapper.between("gmt_create", DateUtils.format(now, "yyyy-MM-dd 00:00:00"), DateUtils.format(now, "yyyy-MM-dd 23:59:59"));
        } else {
            wrapper.between("gmt_create", beginCreatedDate, endCreatedDate);
        }


        // 修复注册证号、批准文号、品类
        List<Material> list = this.list(wrapper).stream()
                .filter(o -> StringUtils.isNotBlank(o.getCertificateNo())
                        && o.getCertificateNo().indexOf("无") == -1
                        && o.getCertificateNo().indexOf("非") == -1
                        && o.getCertificateNo().indexOf("不") == -1
                )
                .collect(Collectors.toList());

        List<MaterialCatalog> code = materialCatalogService.list(
                Wrappers.<MaterialCatalog>query()
                        .isNotNull("code")
                        .select("id,code")
        );

        Map<String, MaterialCatalog> catalogMap = code.stream().filter(o -> StringUtils.isNotBlank(o.getCode())).collect(Collectors.toMap(o -> o.getCode(), o -> o, (o1, o2) -> o1));

        List<Material> result = Lists.newArrayList();
        for (Material material : list) {
            String certNo = material.getCertificateNo().replaceAll("食药监", "")
                    .replaceAll("食药", "")
                    .replaceAll("备案号", "")
                    .replaceAll("[【】（）\\(\\)]", "")
                    .replaceAll("[\\[\\]：:]", "")
                    .replaceAll("\\(", "")
                    .replaceAll("注准字", "注准")
                    .replaceAll("注进字", "注进")
                    .replaceAll("准字", "注准")
                    .replaceAll("进字", "注进")
                    .replaceAll("第", "")
                    .replaceAll("号", "")
                    .replaceAll("\"", "")
                    .replaceAll("\n", "")
                    .trim();

            if (certNo.indexOf("械备") != -1) {
                // 排除备案号
                //未分类
                material.setCatalogId("3000");
                result.add(material);
                continue;
            }
            if (certNo.indexOf("消证") != -1) {
                //未分类
                material.setCatalogId("3000");
                result.add(material);
                continue;
            }
//            if (certNo.indexOf("准字") != -1) {
//                // http://www.nmpa.gov.cn/WS04/CL2158/319341.html
//                // 批准文号
//                material.setApprovalNo(certNo).setCertificateNo("");
//                result.add(material);
//                continue;
//            }

            if (certNo.length() < 14 || certNo.length() > 17) {
                // 长度不对，可能是格式问题
                //未分类
                material.setCatalogId("3000");
                result.add(material);
                log.warn(String.format("注册证号格式错误：%s，长度：%d", certNo, certNo.length()));
                continue;
            }
            // (*{4})(\d{4})(\d)(\d{2})(\d{3,})
            // 国药准字、年份、管理类别、68分类、流水号
            Pattern compile = Pattern.compile("(.{4})(\\d{4})(\\d)(\\d{2})(\\d{3,})");
            Matcher matcher = compile.matcher(certNo);
            if (!matcher.matches()) {
                //未分类
                material.setCatalogId("3000");
                result.add(material);
                continue;
            }
            String catalogCode = "68" + matcher.group(4);
            MaterialCatalog catalog = catalogMap.get(catalogCode);
            if (catalog != null) {
                material.setCatalogId(catalog.getId());
                result.add(material);
            } else {
                //如果品类表没有就保存未分类
                material.setCatalogId("3000");
                result.add(material);
            }
        }
        if (!result.isEmpty()) {
            this.updateBatchById(result);
        }
        log.info("自动修正商品分类完成，修正数据总数：{}", result.size());
    }


    @Override
    protected ExcelImportResult doExcelImport(MultipartFile multipartFile, Map<String, Object> params) throws Exception {
        ImportParams importParams = PoiUtils.getDefaultImportParams();
        long currentTimeMillis = System.currentTimeMillis();
        ExcelImportResult importResult = PoiUtils.importExcelMore(multipartFile.getInputStream(), ExcelMaterialDTO.class, importParams);
        log.info("文件加载耗时：{}", DateUtils.formatTime(System.currentTimeMillis() - currentTimeMillis));

        List<ExcelMaterialDTO> dtoList = Lists.newArrayList(importResult.getList());

        // 查询出所有供应商

        List<String> supplierNames = dtoList.parallelStream().map(o -> o.getSupplierName()).distinct().collect(Collectors.toList());
        List<String> manufactureNames = dtoList.parallelStream().map(o -> o.getManufacturerName()).distinct().collect(Collectors.toList());
        List<String> materialNames = dtoList.parallelStream().map(o -> o.getMaterialName()).distinct().collect(Collectors.toList());
        List<Supplier> supplierList = Lists.newArrayList();
        if (supplierNames != null && supplierNames.size() > 0 ) {
            supplierList = supplierService.list(Wrappers.<Supplier>query().select("id,name").in("name", supplierNames));
        }
        Map<String, Supplier> supplierMap = supplierList.stream().collect(Collectors.toMap(o -> o.getName(), o -> o, (o1, o2) -> o1));
        log.info("加载到{}条供应商数据", supplierMap.size());


        boolean isSupplier = UserUtils.isSupplier();
        String supplierId = null;
        if (isSupplier) {
            supplierId = UserUtils.getSupplierId();
        }

        List<String> supplierIdList = supplierList.stream().map(o -> o.getId()).collect(Collectors.toList());
        List<Manufacturer> manufacturerList = Lists.newArrayList();
        if (manufactureNames != null && manufactureNames.size() > 0) {
            manufacturerList = manufacturerService.list(
                    Wrappers.<Manufacturer>query()
                            .select("id,name,supplier_id")
                            .eq(isSupplier, "supplier_id", supplierId)
                            .in(!isSupplier, "supplier_id", supplierIdList)
                            .in("name", manufactureNames)
            );
        }

        Map<String, Manufacturer> manufacturerMap = manufacturerList.stream().collect(Collectors.toMap(o -> o.getSupplierId() + o.getName(), o -> o, (o1, o2) -> o1));
        log.info("加载到{}条厂商数据", manufacturerMap.size());

        List<Material> materialList = Lists.newArrayList();
        if (materialNames != null && materialNames.size() > 0) {
            materialList = this.list(
                    Wrappers.<Material>query().select("id", "material_name", "material_trade_name", "material_erp_code", "certificate_no", "supplier_id", "manufacturer_id")
                            .in("supplier_id", supplierIdList)
                            .in("material_name", materialNames)
            );
        }
        Map<String, Material> materialMap = materialList.stream().collect(
                Collectors.toMap(o -> o.getSupplierId() + o.getManufacturerId() + o.getMaterialName(), o -> o, (o1, o2) -> o1)
        );

        Map<String, MaterialCatalog> catalogMap = materialCatalogService.list().stream().collect(
                Collectors.toMap(o -> o.getCode(), o -> o, (o1, o2) -> o1)
        );
        log.info("加载到{}条耗材数据", materialMap.size());

        List<String> materialIdList = materialList.stream().map(o -> o.getId()).collect(Collectors.toList());
        List<MaterialSpec> materialSpecList = Lists.newArrayList();
        if (materialIdList != null && materialIdList.size() > 0) {
            materialSpecList = materialSpecService.list(
                    Wrappers.<MaterialSpec>query().select("id", "material_id", "material_spec", "price")
                            .in("material_id", materialIdList)
            );
        }
        Map<String, MaterialSpec> materialSpecMap = materialSpecList.stream().collect(
//                Collectors.toMap(o -> o.getMaterialId() + o.getMaterialSpec() + new BigDecimal(o.getPrice()).setScale(4,BigDecimal.ROUND_HALF_UP), o -> o, (o1, o2) -> o1)
                Collectors.toMap(o -> o.getMaterialId() + o.getMaterialSpec(), o -> o, (o1, o2) -> o1)
        );
        log.info("加载到{}条品规数据", materialSpecMap.size());


        ConcurrentLinkedQueue<MaterialSpecDTO> specDTOS = new ConcurrentLinkedQueue();


        /**  ======================初始数据校验====================== */
        dtoList.stream().forEach(o -> {
            if (StringUtils.isBlank(o.getManufacturerName())) {
                importResult.getList().remove(o);
                o.setErrorMsg(String.format("厂商不能为空"));
                importResult.getFailList().add(o);
                log.warn("第{}行厂商不能为空，请先确认数据是否正确", o.getRowNum());
                return;
            }
            if (!isSupplier && StringUtils.isBlank(o.getSupplierName())) {
                importResult.getList().remove(o);
                o.setErrorMsg(String.format("供应商名称不能为空"));
                importResult.getFailList().add(o);
                log.warn("第{}行供应商名称不能为空，请先确认数据是否正确", o.getRowNum());
                return;
            }
            if (StringUtils.isBlank(o.getMaterialSpec())) {
                importResult.getList().remove(o);
                o.setErrorMsg(String.format("品规不能为空"));
                importResult.getFailList().add(o);
                log.warn("第{}行品规不能为空，请先确认数据是否正确", o.getRowNum());
                return;
            }
        });

        /**  ======================初始数据校验====================== */

        Map<String, List<ExcelMaterialDTO>> map = null;

        if (isSupplier) {
            // 数据分组；EXCEL数据 品名和品规在同一行，所有需要将数据进行分组
            map = dtoList.stream().collect(Collectors.groupingBy(o -> o.getMaterialName() + o.getCatalogName() + o.getManufacturerName()));
        } else {
            // 数据分组；EXCEL数据 品名和品规在同一行，所有需要将数据进行分组
            map = dtoList.stream().collect(Collectors.groupingBy(o -> o.getMaterialName() + o.getCatalogName() + o.getManufacturerName() + o.getSupplierName()));
        }
        //分组后把每一组存入list
        List<List<ExcelMaterialDTO>> ldtoList = Lists.newArrayListWithCapacity(map.size());
        for (String key : map.keySet()) {
            ldtoList.add(map.get(key));
        }


        DefaultSaveHandler<List<ExcelMaterialDTO>> saveHandler = new DefaultSaveHandler<List<ExcelMaterialDTO>>() {
            @Override
            public void doSave(int currentIndex, List<ExcelMaterialDTO> listentity) throws BusinessException {
                // 先保存商品数据，由于已经经过分组，所以list中数据关于商品的数据一致，直接取第一行
                ExcelMaterialDTO emDTO = listentity.get(0);
                Material m = new Material();
                BeanUtils.copyProperties(emDTO, m);

                if  (StringUtils.isNotBlank(emDTO.getCatalogCode()) && (catalogMap == null || !catalogMap.containsKey(emDTO.getCatalogCode()))) {
                    importResult.getList().remove(emDTO);
                    emDTO.setErrorMsg(StrUtil.format("品类代码{}不存在",emDTO.getCatalogCode()));
                    importResult.getFailList().add(emDTO);
                    log.warn("第{}行品类不存在，请先确认数据是否正确；品类代码：{}", emDTO.getRowNum(), emDTO.getCatalogCode());
                    return;
                }
                m.setCatalogId(catalogMap.get(emDTO.getCatalogCode()).getId()).setCatalogName(catalogMap.get(emDTO.getCatalogCode()).getName());


                if (isSupplier) {
                    m.setSupplierId(UserUtils.getSupplierId());
                    m.setSupplierName(UserUtils.getSupplier().getName());
                    Manufacturer manufacturer = manufacturerMap.get(UserUtils.getSupplierId() + emDTO.getManufacturerName());
                    if (manufacturer == null) {
                        importResult.getList().remove(emDTO);
                        emDTO.setErrorMsg(String.format("厂商不存在"));
                        importResult.getFailList().add(emDTO);
                        log.warn("第{}行厂商不存在，请先确认数据是否正确；厂商名称：{}", emDTO.getRowNum(), emDTO.getManufacturerName());
                        return;
                        // continue;
                    }
                    m.setManufacturerId(manufacturer.getId());
                } else {
                    String supplierName = emDTO.getSupplierName();
                    Supplier supplier = supplierMap.get(supplierName);


                    if (supplier == null) {
                        importResult.getList().remove(emDTO);
                        emDTO.setErrorMsg(String.format("供应商不存在"));
                        importResult.getFailList().add(emDTO);
                        log.warn("第{}行供应商不存在，请先确认数据是否正确；供应商名称：{}", emDTO.getRowNum(), supplierName);
                        return;
                    }
                    m.setSupplierId(supplier.getId());
                    m.setSupplierName(supplier.getName());

                    //查询出该条件下厂商信息
                    /*Manufacturer manufacturer = manufacturerService.getOne(Wrappers.<Manufacturer>query()
                            .select("id,name")
                            .eq("supplier_id", supplier.getId())
                            .eq("name", emDTO.getManufacturerName())
                            .last("limit 1")
                    );*/
                    Manufacturer manufacturer = manufacturerMap.get(supplier.getId() + emDTO.getManufacturerName());
                    if (manufacturer == null) {
                        importResult.getList().remove(emDTO);
                        importResult.getFailList().add(emDTO);
                        emDTO.setErrorMsg(String.format("厂商不存在"));
                        log.warn("第{}行厂商不存在，请先确认数据是否正确；厂商名称：{}", emDTO.getRowNum(), emDTO.getManufacturerName());
                        return;
                        //continue;
                    }
                    m.setManufacturerId(manufacturer.getId());
                }

                //查询数据库是否有该商品，如果有就更新，没有就保存
               /* Material material = getOne(Wrappers.<Material>query()
                        .eq("supplier_id", m.getSupplierId())
                        .eq(StringUtils.isNotBlank(m.getCatalogId()), "catalog_id", m.getCatalogId())
                        .eq(StringUtils.isNotBlank(m.getManufacturerId()), "manufacturer_id", m.getManufacturerId())
                        .eq(StringUtils.isNotBlank(m.getMaterialName()), "material_name", m.getMaterialName())
                        .last("limit 1")
                );*/
                Material material = materialMap.get(m.getSupplierId() + m.getManufacturerId() + m.getMaterialName());
                if (material != null) {
                    m.setId(material.getId());
                    updateById(m);
                } else {
                    String pinyin = PinYinUtils.getAlpha(m.getMaterialName());
                    m.setPinyin(StringUtils.substring(pinyin, 0, 10));
                    save(m);
                    materialMap.put(m.getSupplierId() + m.getManufacturerId() + m.getMaterialName(), m);
                }

                // 保存品规
                listentity.stream().forEach(o -> o.setMaterialId(m.getId()));
                for (ExcelMaterialDTO dto : listentity) {
                    //查询数据库该品规是否存在，存在就更新不存在就保存
                   /* MaterialSpec materialSpec = materialSpecService.getOne(Wrappers.<MaterialSpec>query()
                            .eq(StringUtils.isNotBlank(dto.getMaterialId()), "material_id", dto.getMaterialId())
                            .eq(StringUtils.isNotBlank(dto.getMaterialSpec()), "material_spec", dto.getMaterialSpec())
                            .last("limit 1")
                    );*/

                    BigDecimal price = new BigDecimal(dto.getPrice()).setScale(4, BigDecimal.ROUND_HALF_UP);
                    MaterialSpec materialSpec = materialSpecMap.get(dto.getMaterialId() + dto.getMaterialSpec());
//                    MaterialSpec materialSpec = materialSpecMap.get(dto.getMaterialId() + dto.getMaterialSpec() + price);
                    MaterialSpecDTO spec = new MaterialSpecDTO();
                    if (materialSpec != null) {
                        spec.setId(materialSpec.getId());
                    }
                    spec.setMaterialId(dto.getMaterialId())
                            .setMaterialSpec(dto.getMaterialSpec())
                            .setInputCodingType(dto.getInputCodingType())
                            .setInputCode(dto.getInputCode())
                            .setForm(dto.getForm())
                            .setUnit(dto.getUnit())
                            .setOrderQty(1.0)
                            .setOrderUnit(dto.getUnit())
                            .setPrice(dto.getPrice())
                            .setIsConsignment(dto.getIsConsignment())
                            .setIsOneThingOneYard(dto.getIsOneThingOneYard())
                            .setCertificateNo(m.getCertificateNo())
                            .setCertificateExpiredDate(m.getCertificateExpiredDate())
                            .setCertificateExpiredStartDate(m.getHospitalCertificateExpiredStartDate());
                    specDTOS.add(spec);
                }
            }
        };
        BatchSaveTask<ExcelMaterialDTO> task = new BatchSaveTask(saveHandler, ldtoList);

        this.forkJoinPool.invoke(task);

        List<MaterialSpec> specs = Lists.newArrayList();
        BeanUtils.copyProperties(Lists.newArrayList(specDTOS), specs, MaterialSpec.class);

        List<MaterialSpec> updateSpecs = specs.stream().filter(o -> StringUtils.isNotBlank(o.getId())).collect(Collectors.toList());
        List<MaterialSpec> insertSpecs = specs.stream().filter(o -> StringUtils.isBlank(o.getId())).collect(Collectors.toList());
        if (!updateSpecs.isEmpty()) {
            materialSpecService.updateBatchById(updateSpecs);
        }
        if (!insertSpecs.isEmpty()) {
            //materialSpecService.saveBatch(insertSpecs);
            materialSpecService.insertBatchSomeColumn(Lists.newArrayList(insertSpecs));
        }
        return importResult;
    }

    @Override
    public IPage<Material> page(IPage<Material> page, Wrapper<Material> queryWrapper) {
        return super.page(page, queryWrapper);
    }

    // 批量禁用
    @Override
    @Transactional(rollbackFor = Exception.class)
    public String disabledBatch(DisabledParamDTO disabledParam, boolean isDisabled) {
        List<Material> materialList = this.list(Wrappers.<Material>query().in("id",disabledParam.getIdList()));
        BusinessException.throwErrorIf(materialList.isEmpty(), "所操作的数据不存在，请刷新重试");

        String loginUid = UserUtils.currentUser().getId();
        String nowTime = DateUtils.nowDate(DateUtils.DEFAULT_PATTER);
        String remark = StrUtil.format("{},{}[用户手动禁用]",disabledParam.getRemark(),nowTime);
        remark = UtilCommon.getStringPre(remark, 200);;

        this.update(
                Wrappers.<Material>update()
                        .ne("flag_disabled_scp",isDisabled)
                        .in("id",disabledParam.getIdList())
                        .set("gmt_modified",nowTime)
                        .set("modifier",loginUid)
                        .set("flag_disabled_scp",isDisabled)
                        .set(isDisabled,"disabled_remark_scp",remark)
        );

//        hospitalMaterialMapper.update(
//                new HospitalMaterial(),
//                Wrappers.<HospitalMaterial>update()
//                        .ne("inactive",!isDisabled)
//                        .in("material_id",disabledParam.getIdList())
//                        .set("gmt_modified",nowTime)
//                        .set("modifier",loginUid)
//                        .set("inactive",!isDisabled)
//                        .set(isDisabled,"disabled_remark_scp",remark)
//        );

        return StrUtil.format("操作成功");
    }

    @Override
    public boolean saveOrUpdate(Material entity) {
        entity.setPinyin(UtilCommon.getStringPre(PinYinUtils.getAlpha(entity.getMaterialName()),30));
        entity.setMaterialTradeName(entity.getMaterialName());
        super.saveOrUpdate(entity);
        if (entity.getMaterialSpec() != null) {
            entity.getMaterialSpec().setMaterialId(entity.getId());
            materialSpecService.saveOrUpdate(entity.getMaterialSpec());
        }

        // 更新已供货商品
        SingleService.inst.hospitalMaterialService.updateFromMaterialChange(entity);
        return true;
    }


    // 导入商品
    @Transactional(rollbackFor = Exception.class)
    @Override
    public RestResult excelImportForDataImport(MultipartFile file, Map<String, String> reqData) {
        List<MaterialImportDto> itemImportList = (List<MaterialImportDto>) excelGetDataList(file,reqData, ExcelImportBaseDataConfig.getMatrDataImport(),MaterialImportDto.class);
        Integer successCount = 0,failCount = 0;
        List<String> msgList = new ArrayList<>();

        // 供应商
        List<String> supplierNameList = itemImportList.stream().map(o -> o.getSupplierName()).distinct().collect(Collectors.toList());
        if (UserUtils.isSupplier() && !supplierNameList.contains(UserUtils.getSupplier().getName())) {
            BusinessException.throwError("请导入当前登录供应商[{}]的商品",UserUtils.getSupplier().getName());
        }

        List<Supplier> supplierList = supplierService.list(Wrappers.<Supplier>query().select("id,name").in("name", supplierNameList));
        if (ObjectUtil.length(supplierNameList) != ObjectUtil.length(supplierList)) {
            List<String>  supplierNameListDb = supplierList.stream().map(o -> o.getName()).distinct().collect(Collectors.toList());
            supplierNameList.stream().filter(find -> !supplierNameListDb.contains(find)).findFirst().ifPresent(find2 -> {
                BusinessException.throwError("供应商[{}]不存在,请先创建供应商",find2);
            });
        }

        Map<String, Supplier> spGroupByName = supplierList.stream().collect(Collectors.toMap(o -> o.getName(), o -> o, (o1, o2) -> o1));

        // 厂商
        List<String> manufactureNames = itemImportList.stream().map(o -> o.getManufacturerName()).distinct().collect(Collectors.toList());
        List<String> supplierIdList = supplierList.stream().map(o -> o.getId()).collect(Collectors.toList());
        List<Manufacturer> manufacturerList = manufacturerService.list(
                Wrappers.<Manufacturer>query()
                        .select("id,name,supplier_id")
                        .in( "supplier_id", supplierIdList)
                        .in("name", manufactureNames)
        );
        Map<String, Manufacturer> mfgMapBySpIdAndMfgName = manufacturerList.stream().collect(Collectors.toMap(o -> o.getSupplierId() + o.getName(), o -> o, (o1, o2) -> o1));


        // 供应商id、商品名称、商品规格、生产厂家 去重
        String tms = "_"+System.currentTimeMillis() + "_";
        Map<String,MaterialSpec> matrUnqMap = materialSpecMapper.listSpecUnq(Wrappers.<MaterialSpec>query().in("supplier_id",supplierIdList))
                .stream().collect(Collectors.toMap(find -> find.getSupplierId() +tms + find.getMaterialName() +tms  + find.getMaterialSpec()+tms + find.getManufacturerId(), t -> t));

        List<Manufacturer> mfgAddList = new ArrayList<>();
        List<Material> matrAddList = new ArrayList<>();
        List<MaterialSpec> matrSpecAddList = new ArrayList<>();

        // 遍历导入数据
        Manufacturer mfgFind;
        Material matrAdd;
        MaterialSpec matrSpecAdd;
        String matrUnqKey ;
        List<String> matrUnqKeyAddList = new ArrayList<>();
        int rowIndex = 0;
        String remark = StrUtil.format(
                "商品导入，时间:{},操作人:{}",
                DateUtils.nowDate(DateUtils.YYYYMMDDHHMMSS_PATTER2),
                UserUtils.currentUser().getNickname()
        );
        for(MaterialImportDto importItem : itemImportList) {
            matrAdd = new Material();
            rowIndex++;
            BeanUtils.copyProperties(importItem, matrAdd);

            // 供应商
            matrAdd.setSupplierId(spGroupByName.get(importItem.getSupplierName()).getId());

            // 厂商
            mfgFind = mfgMapBySpIdAndMfgName.get(matrAdd.getSupplierId() + matrAdd.getManufacturerName());
            if (mfgFind == null) {
                //添加厂商信息
                mfgFind = new Manufacturer();
                String pinyin = PinYinUtils.getAlpha(importItem.getManufacturerName());
                mfgFind.setSupplierId(matrAdd.getSupplierId())
                        .setName(matrAdd.getManufacturerName())
                        .setPinyin(StringUtils.substring(pinyin, 0, 10));
                mfgFind.setId(IdWorker.getIdStr());
                mfgMapBySpIdAndMfgName.put(matrAdd.getSupplierId() + matrAdd.getManufacturerName(), mfgFind);
                mfgAddList.add(mfgFind);
            }
            matrAdd.setManufacturerId(mfgFind.getId());

            // 商品其他属性
            matrAdd.setCatalogId("0");
            matrAdd.setMaterialTradeName(matrAdd.getMaterialName());
            matrAdd.setMaterialTypeCode(Material.TYPE_CODE_CONSUMABLES +"");
            matrAdd.setPinyin(StringUtils.substring(PinYinUtils.getAlpha(matrAdd.getMaterialName()), 0, 30));
            matrAdd.setRemark(remark);
            matrAdd.setHisMedicareName(matrAdd.getHisMedicareName2());

            // 供应商id、商品名称、商品规格、生产厂家 去重
            matrUnqKey = matrAdd.getSupplierId()+tms + matrAdd.getMaterialName()+tms   + importItem.getMaterialSpecInput()+tms + matrAdd.getManufacturerId();
            if (matrUnqKeyAddList.contains(matrUnqKey) || matrUnqMap.containsKey(matrUnqKey)) {
                failCount++;
                msgList.add(StrUtil.format("第{}行,已存在同供应商、同商品名称、同厂商、同规格商品，忽略新增", rowIndex));
                continue;
            }
            matrUnqKeyAddList.add(matrUnqKey);

            matrAdd.setId(IdWorker.getIdStr());
            matrAddList.add(matrAdd);
            successCount++;


            matrSpecAdd = new MaterialSpec();
            BeanUtils.copyProperties(importItem, matrSpecAdd);
            matrSpecAdd.setMaterialId(matrAdd.getId());
            matrSpecAdd.setMaterialSpec(importItem.getMaterialSpecInput());
            matrSpecAdd.setInputCodingType(0+"");
            if (StringUtils.isBlank(matrSpecAdd.getOrderUnit())) {
                matrSpecAdd.setOrderUnit(matrSpecAdd.getUnit());
            }
            if (
                matrSpecAdd.getUnit().equals(matrSpecAdd.getOrderUnit())
                ||
                (
                        matrSpecAdd.getOrderQty() == null || matrSpecAdd.getOrderQty() <= 0
                )
            ) {
                matrSpecAdd.setOrderQty(1d);
            }
            matrSpecAddList.add(matrSpecAdd);
        }


        if (!mfgAddList.isEmpty()) {
            manufacturerService.saveBatch(mfgAddList);
        }

        if (!matrAddList.isEmpty()) {
            this.saveBatch(matrAddList);
        }

        if (!matrSpecAddList.isEmpty()) {
            materialSpecService.saveBatch(matrSpecAddList);
        }

        ImportResult result = new ImportResult();
        result.setTotalCount(itemImportList.size());
        result.setSuccessCount(successCount);
        result.setFailCount(failCount);
        result.setMessages(msgList);
        return RestResult.ok("商品导入成功",result);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean removeCascadeBatchByIds(Collection<? extends Serializable> idList) {
        HospitalMaterial findOne = hospitalMaterialMapper.selectOne(Wrappers.<HospitalMaterial>query().in("material_id", idList).last("limit 1"));
        if (findOne != null) {
            BusinessException.throwError("商品[{}]已进行供货，不允许删除",this.getById(findOne.getMaterialId()).getMaterialName());
        }

        hospitalMaterialMapper.delete(Wrappers.<HospitalMaterial>query().in("material_id", idList));
        materialSpecMapper.delete(Wrappers.<MaterialSpec>query().in("material_id", idList));
        return super.removeCascadeBatchByIds(idList);
    }
}
